package org.jfsm.concurrent;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;

import org.jfsm.log.LogSource;

public class ConcurrentContext {

    LogSource logger = new LogSource();

    private final AtomicLong ref = new AtomicLong();

    private final ConcurrentLinkedQueue<Work> queue = new ConcurrentLinkedQueue<Work>();

    /**
     * Try locking the context. If failed, enqueue the work
     * 
     * @param workerID
     * @param work
     * @return true if context successfully locked.
     */
    final boolean lockOrEnqueue(Work work) {
        if (ref.getAndIncrement() == 0) {
            return true;
        } else {
            queue.offer(work);
            return false;
        }
    }

    final Work dequeue() {
        Work work;

        while ((work = queue.poll()) == null) {
            logger.log("Context dequeue:", "Yield");
            Thread.yield();
        }

        return work;
    }

    /**
     * Release the context.
     * 
     * @return false if there are queued items.
     */
    final boolean release() {
        return (ref.decrementAndGet() == 0);
    }
}
